
#include<iostream>
#include<string>
#include<cstring>
#include<cstdlib>

#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>

#include"Log.hpp"
#include"nocopy.hpp"
#include"Comm.hpp"

const static int default_backlog=5;//TODO

class TcpServer :public nocopy
{
   public:
   TcpServer(uint16_t port)
   :_port(port),_isrunning(false)
   {}
  
   //初始化，也是固定套路
   void Init()
   {
    //创建套接字
    _listensock =socket(AF_INET,SOCK_STREAM,0);
    if(_listensock<0)
    {
        lg.LogMessage(Fatal,"创建套接字失败，失败码: %d,失败信息:%s\n",errno,strerror(errno));
        exit(Fatal);
    }
    lg.LogMessage(Debug,"创建套接字成功，sockfd: %d\n",_listensock);

    //填充本地网络信息并bind
    struct sockaddr_in local;
    memset(&local,0,sizeof(local));
    local.sin_family =AF_INET;
    local.sin_port =htons(_port);
    local.sin_addr.s_addr=htonl(INADDR_ANY);
    //BIND
    if(bind(_listensock,CONV(&local),sizeof(local))!=0)
    {
        lg.LogMessage(Fatal,"bind失败，失败码: %d,失败信息:%s\n",errno,strerror(errno));
        exit(Bind_Err);
    }
    lg.LogMessage(Debug,"bind成功，sockfd: %d\n",_listensock);
    
    //设置socket 为监听状态，tcp特有的
    if(listen(_listensock,default_backlog)!=0)
    {
         lg.LogMessage(Fatal,"监听套接字失败，失败码: %d,失败信息:%s\n",errno,strerror(errno));
         exit(Listen_Err);
    }
    lg.LogMessage(Debug,"监听成功，sockfd: %d\n",_listensock);
   }
   
   //tcp 连接全双工通信
   void Service(int sockfd)
   {
     char buffer[1024];

     while(true)
     {
        ssize_t n = read(sockfd,buffer,sizeof(buffer)-1);
        if(n>0)
        {
            buffer[n]=0;
            std::cout<<"客户端发："<<buffer<<std::endl;

            std::string echo_string ="服务端 回:";
            echo_string +=buffer;
            write(sockfd,echo_string.c_str(),echo_string.size());//往文件描述符里写消息
        
        }
        else if (n==0)
        {
            lg.LogMessage(Info,"客户端退出...\n");
            break;
        }
        else
        {
         lg.LogMessage(Fatal,"读取套接字失败，失败码: %d,失败信息:%s\n",errno,strerror(errno));   
         break;
        }
     }

   }
   
   //开始
   void Statr()
   {
    _isrunning =true;
    while(_isrunning)
    {
       //获取连接
       struct sockaddr_in peer;
       socklen_t len = sizeof(peer);

       int sockfd =accept(_listensock,CONV(&peer),&len);
       if(sockfd<0)
       {
         lg.LogMessage(Fatal,"接收套接字失败，失败码: %d,失败信息:%s\n",errno,strerror(errno));   
        continue;
       }
        lg.LogMessage(Debug,"接收成功 sockfd: %d\n",_listensock);
        // 提供服务
        Service(sockfd);
        close(sockfd);
    }

   }

   ~TcpServer()
     {

     }

    private:
    uint16_t _port; //端口
    int _listensock;//监听？
    bool _isrunning;
};